package com.ly.bluetoothlowenergydemo;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

/**
 * 蓝牙串口SPP Demo
 *
 * @author Liuyang
 * @date 2020/5/28
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener, BLESPPUtils.OnBluetoothAction {
    /**
     * 蓝牙工具
     */
    private BLESPPUtils blesppUtils;

    /**
     * 保存搜索到的设备，避免重复
     */
    private ArrayList<BluetoothDevice> deviceList = new ArrayList<>();

    /**
     * 对话框控制器
     */
    private DeviceDialogControl deviceDialogControl;

    /**
     * log视图
     */
    private TextView tvLog;

    /**
     * 输入的内容
     */
    private EditText etInput;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 申请权限
        initPermissions();
        // 绑定视图
        findViewById(R.id.btn_send).setOnClickListener(this);
        tvLog = findViewById(R.id.tv_log);
        etInput = findViewById(R.id.et_input);

        // 初始化
        blesppUtils = new BLESPPUtils(this, this);
        // 启动日志输出
        blesppUtils.setEnableLogOut();
        // 设置接收停止标志位字符串
        blesppUtils.setStopString("\r\n");
        // 用户没有开启蓝牙的话，打开蓝牙
        if (!blesppUtils.isBluetoothEnable()) {
            blesppUtils.enableBluetooth();
        }
        // 启动工具类
        blesppUtils.onCreate();

        deviceDialogControl = new DeviceDialogControl(this);
        deviceDialogControl.show();
    }

    @Override
    protected void onDestroy() {
        blesppUtils.onDestory();
        super.onDestroy();
    }

    /**
     * 申请权限
     */
    private void initPermissions() {
        if (ContextCompat.checkSelfPermission(this, "android.permission-group.LOCATION") != 0) {
            ActivityCompat.requestPermissions(this, new String[]{
                    "android.permission.ACCESS_FINE_LOCATION",
                    "android.permission.ACCESS_COARSE_LOCATION",
                    "android.permission.ACCESS_WIFI_STATE"
            }, 1);
        }
    }

    /**
     * 发现新设备
     *
     * @param device 设备
     */
    @Override
    public void onFoundDevice(BluetoothDevice device) {
        Log.d("BLE", "发现设备：" + device.getName() + "--" + device.getAddress());
        // 判断是不是重复的
        for (int i = 0; i < deviceList.size(); i++) {
            if (deviceList.get(i).getAddress().equals(device.getAddress())) {
                return;
            }
        }
        // 添加
        deviceList.add(device);
        // 添加条目到UI，并设置点击事件
        deviceDialogControl.addDevice(device, new View.OnClickListener() {
            @SuppressLint("SetTextI18n")
            @Override
            public void onClick(View v) {
                BluetoothDevice clickDevice = (BluetoothDevice) v.getTag();
                postShowToast("开始连接：" + clickDevice.getName());
                tvLog.setText(tvLog.getText() + "\n开始连接：" + clickDevice.getName());
                blesppUtils.connect(clickDevice);
            }
        });
    }

    /**
     * 连接成功
     *
     * @param device 设备
     */
    @Override
    public void onConnectSuccess(final BluetoothDevice device) {
        postShowToast("连接成功", new DoSthAfterPost() {
            @SuppressLint("SetTextI18n")
            @Override
            public void doIt() {
                tvLog.setText(tvLog.getText() + "\n连接成功：" + device.getName() + " | " + device.getAddress());
                deviceDialogControl.dismiss();
            }
        });
    }

    /**
     * 连接失败
     *
     * @param msg 信息
     */
    @Override
    public void onConnectFailed(final String msg) {
        postShowToast("连接失败：" + msg, new DoSthAfterPost() {
            @SuppressLint("SetTextI18n")
            @Override
            public void doIt() {
                tvLog.setText(tvLog.getText() + "\n连接失败：" + msg);
            }
        });
    }

    /**
     * 接收数据
     *
     * @param bytes 内容
     */
    @Override
    public void onReceiveBytes(final byte[] bytes) {
        postShowToast("收到数据：" + new String(bytes), new DoSthAfterPost() {
            @SuppressLint("SetTextI18n")
            @Override
            public void doIt() {
                tvLog.setText(tvLog.getText() + "\n收到数据：" + new String(bytes));
            }
        });

    }

    /**
     * 发送数据
     *
     * @param bytes 内容
     */
    @Override
    public void onSendBytes(final byte[] bytes) {
        postShowToast("发送数据：" + new String(bytes), new DoSthAfterPost() {
            @SuppressLint("SetTextI18n")
            @Override
            public void doIt() {
                tvLog.setText(tvLog.getText() + "\n发送数据：" + new String(bytes));
            }
        });
    }

    /**
     * 结束搜索设备
     */
    @Override
    public void onFinishFoundDevice() {
    }

    /**
     * 按钮的点击事件
     *
     * @param v 点击的按钮
     */
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.btn_send) {
            blesppUtils.send((etInput.getText().toString() + "\n").getBytes());
        }
    }

    /**
     * 设备选择对话框控制
     */
    private class DeviceDialogControl {
        private LinearLayout dialogRootView;
        private ProgressBar progressBar;
        private AlertDialog connectDeviceDialog;

        DeviceDialogControl(Context context) {
            // 搜索进度条
            progressBar = new ProgressBar(context, null, android.R.attr.progressBarStyleHorizontal);
            progressBar.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 50));

            // 根布局
            dialogRootView = new LinearLayout(context);
            dialogRootView.setOrientation(LinearLayout.VERTICAL);
            dialogRootView.addView(progressBar);
            dialogRootView.setMinimumHeight(700);

            // 容器布局
            ScrollView scrollView = new ScrollView(context);
            scrollView.addView(dialogRootView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, 700));

            // 构建对话框
            connectDeviceDialog = new AlertDialog.Builder(context)
                    .setNegativeButton("刷新", null)
                    .setPositiveButton("退出", null)
                    .create();
            connectDeviceDialog.setTitle("选择连接的蓝牙设备");
            connectDeviceDialog.setView(scrollView);
            connectDeviceDialog.setCancelable(false);
        }

        /**
         * 显示并开始搜索设备
         */
        void show() {
            blesppUtils.startDiscovery();
            connectDeviceDialog.show();
            connectDeviceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    connectDeviceDialog.dismiss();
                    return true;
                }
            });
            connectDeviceDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    connectDeviceDialog.dismiss();
                    finish();
                }
            });
            connectDeviceDialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dialogRootView.removeAllViews();
                    dialogRootView.addView(progressBar);
                    deviceList.clear();
                    blesppUtils.startDiscovery();
                }
            });
        }

        /**
         * 取消对话框
         */
        void dismiss() {
            connectDeviceDialog.dismiss();
        }

        /**
         * 添加一个设备到列表
         *
         * @param device          设备
         * @param onClickListener 点击回调
         */
        private void addDevice(final BluetoothDevice device, final View.OnClickListener onClickListener) {
            runOnUiThread(new Runnable() {
                @SuppressLint("SetTextI18n")
                @Override
                public void run() {
                    TextView devTag = new TextView(MainActivity.this);
                    devTag.setClickable(true);
                    devTag.setPadding(20, 20, 20, 20);
                    devTag.setBackgroundResource(R.drawable.rect_round_button_ripple);
                    devTag.setText(device.getName() + "\nMAC:" + device.getAddress());
                    devTag.setTextColor(Color.WHITE);
                    devTag.setOnClickListener(onClickListener);
                    devTag.setTag(device);
                    devTag.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                            ViewGroup.LayoutParams.WRAP_CONTENT));

                    ((LinearLayout.LayoutParams) devTag.getLayoutParams()).setMargins(20, 20, 20, 20);
                    dialogRootView.addView(devTag);
                }
            });
        }
    }

    /**
     * 在主线程弹出Toast
     *
     * @param msg 信息
     */
    private void postShowToast(final String msg) {
        postShowToast(msg, null);
    }

    private void postShowToast(final String msg, final DoSthAfterPost doSthAfterPost) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
                if (doSthAfterPost != null) {
                    doSthAfterPost.doIt();
                }
            }
        });
    }

    private interface DoSthAfterPost {
        /**
         * 做一些事情
         */
        void doIt();
    }
}
